#pragma once

#include <memory>
#include <vulkan/vulkan.hpp>
#include "Containers/Vector.h"
#include "Math/Matrix4x4.h"
#include "Render/VulkanMemory/MemoryPool.h"
#include "Render/VulkanMemory/FixedUniformBuffer.h"

#include "VulkanPixelObjectViewUniformBuffer.h"

class CVulkanMesh;
class CVulkanImage;
class CVulkanUniformBuffer;
class CPreRenderPixelObjectMesh;
class CPreRenderPixelObjectGroup;
class CPixelObjectMapID;

class CVulkanViewportWidget;

class CVulkanPixelObjectMeshBatch
{
public:
    CVulkanPixelObjectMeshBatch();

    void PreProcess(
        std::shared_ptr<CPreRenderPixelObjectMesh> InMeshInstance
        ,CVulkanViewportWidget* InViewport
    );
    void Draw(
        vk::CommandBuffer InCmdBuffer
        ,vk::DescriptorSet InViewInfoDescriptorSet
        );

    void CreateDescriptorSet();
protected:

    std::shared_ptr<CVulkanMesh> Mesh;  
    int32_t InstanceNum = 0;
    int32_t BatchNum = 0;
    // TVector<SMatrix4x4> ModelMatrices;
    // TVector<uint16_t> ObjectIDs;  

    //所有实例的数据
    std::shared_ptr<CVulkanUniformBuffer> ModelUniformBuffer;

    void CountDescriptorSet();

    //批描述符集，索引对应小批次
    TVector<vk::DescriptorSet> ModelBufferDescriptorSets;
};

//渲染像素对象实例组
class CVulkanPixelObjectGroup
{

public:    
    CVulkanPixelObjectGroup();
    ~CVulkanPixelObjectGroup();
    void PreProcess(
        std::shared_ptr<CPreRenderPixelObjectGroup> InPixelObjectGroup
        ,CVulkanViewportWidget* InViewport
    );

    void Draw(vk::CommandBuffer InCmdBuffer);
protected:
    vk::Extent2D ViewportSize;
    vk::Extent2D RenderTargetSize;

    std::shared_ptr<CVulkanImage> ColorImage;
    vk::ImageView ColorImageView;
    std::shared_ptr<CVulkanImage> DepthImage;
    vk::ImageView DepthImageView;

    vk::Framebuffer FrameBuffer;


    std::shared_ptr<
        TVulkanUniformBuffer<
           SPixelObjectViewUniformBuffer
        >
    > ViewInfoBuffer;
    vk::DescriptorSet ViewInfoDescriptorSet;
    void CreateViewInfoDescriptorSet();

    TVector<CVulkanPixelObjectMeshBatch> MeshBatchs;

    TVector<CVulkanPixelObjectMeshBatch> ForegroundMeshBatchs;

    //最终渲染选目标像素
    TThreadSafeSharedPtr<CPixelObjectMapID> RenderTargetID;
    SVulkanAutoRecycleBuffer RenderTargetBuffer;
    //通知同缓冲区的前一帧已经渲染完成
    void NotifyFormerFrameFinished();
};
